package com.wl.common.security.interceptor;

import com.wl.common.security.bean.IgnoreUrlsProperties;
import com.wl.common.security.register.SecurityMetadataSource;
import com.wl.common.security.utils.JwtTokenUtil;
import com.wl.common.security.utils.ServletUtils;
import com.wl.system.api.model.LoginUser;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

/**
 * @author: wanglin
 * @date: 2024-03-08 周五
 * @Version: 1.0
 * @Description: 权限拦截器
 */
public class AuthorityInterceptor implements AsyncHandlerInterceptor {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private IgnoreUrlsProperties ignoreUrlList;

    @Autowired
    private SecurityMetadataSource metadataSource;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        String currentUri = request.getRequestURI();

        // 不需要保护的资源路径允许访问swagger等,这里主要是针对放行接口并携带了token的路径，则直接放行；如：注册接口，带了token；
        PathMatcher pathMatcher = new AntPathMatcher();

        //1-是否存在token
        String token = jwtTokenUtil.getToken(request);

        //2-token正确性验证，内存中是否存在该登录用户，一般存储在Redis，这里是存在内存中
        LoginUser loginUser = jwtTokenUtil.getLoginUserByToken(token);
        if (ObjectUtils.isEmpty(loginUser)) {
            ServletUtils.resultInvalid(response);
            return false;
        }

        //验证token是否和用户token一致;根据toke中的user_key标识验证
        String userKey = jwtTokenUtil.getUserKey(token);
        if (!loginUser.getToken().equals(userKey)) {
            ServletUtils.resultInvalid(response);
            return false;
        }

        //若已经登录，则放行公共接口
        for (String url : ignoreUrlList.getApis()) {
            if (pathMatcher.match(url, currentUri)) {
                return true;
            }
        }

        //获取访问该路径所需的
        ConcurrentMap<String, String> resourceMap = metadataSource.getResourceMap();
//        boolean flag = false;
//        resourceMap.forEach((url, role) -> {
//            if (pathMatcher.match(url, currentUri) && loginUser.getRoles().contains(role)) {
//                return;
//            }
//        });
        for (Map.Entry<String, String> entry : resourceMap.entrySet()) {
            if (pathMatcher.match(entry.getKey(), currentUri) && loginUser.getRoles().contains(entry.getValue())) {
                return true;
            }
        }

        //对当前接口访问角色验证, 获取当前用户角色
//        Set<String> roles = loginUser.getRoles();
        ServletUtils.resultNotPermission(response);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 返回json


//        HandlerMethod handlerMethod = new HandlerMethod(((HandlerMethod) handler).getBean(), ((HandlerMethod) handler).getMethod());
//        Object returnValue = interceptorPreHandler.getResponseBody();
//        MethodParameter returnValueType = handlerMethod.getReturnValueType(returnValue);
//        applicationContext.getBean(RequestMappingHandlerAdapter.class).getReturnValueHandlers();
//        RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor = findRequestResponseBodyMethodProcessor();
//        requestResponseBodyMethodProcessor.handleReturnValue(returnValue, returnValueType, new ModelAndViewContainer(), new ServletWebRequest(request, response));

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        SecurityContextHolder.remove();
    }
}
